﻿using System;
using System.Diagnostics;
using System.Windows.Media.Imaging;
using Redbrick.Silverlight.Extentions;
using System.Windows.Media;
using Moria.Silverlight.Enum;

namespace Moria.Silverlight.Model
{


	public class InventoryItem : Drawable
	{

		#region Consts & Settings

		public const int ITEM_SINGLE_STACK_MIN = 64;
		public const int ITEM_SINGLE_STACK_MAX = 192;
		public const int ITEM_GROUP_MIN = 192;
		public const int ITEM_GROUP_MAX = 255;
		/* Magic Treasure Generation constants				*/
		/* Note: Number of special objects, and degree of enchantments	 */
		/*	 can be adjusted here.					 */
		public const int OBJ_STD_ADJ = 125;/* Adjust STD per level * 100	       */
		public const int OBJ_STD_MIN = 7;/* Minimum STD			       */
		public const int OBJ_TOWN_LEVEL = 7;   /* Town object generation level	       */
		public const int OBJ_BASE_MAGIC = 15;  /* Base amount of magic		       */
		public const int OBJ_BASE_MAX = 70;   /* Max amount of magic		       */
		public const int OBJ_DIV_SPECIAL = 6;    /* magic_chance/#	 special magic	      */
		public const int OBJ_DIV_CURSED = 13;   /* 10*magic_chance/#  cursed items	 */
		public const int OBJECT_IDENT_SIZE = 448;
		#endregion Consts & Settings

		#region Declarations

		static ObjectDescription[] object_ident = new ObjectDescription[OBJECT_IDENT_SIZE];
		
		private InventoryLocation _location = InventoryLocation.None;
		private string _inscrip = string.Empty;
		private ItemFlag _flags = ItemFlag.NULL;
		private int _misc = 0;
		private int _cost = 0;
		private int _itemCount = 0;
		private int _weight = 0;
		private int _toHit = 0;
		private int _toDamage = 0;
		private int _armorClass = 0;
		private int _toArmorClass = 0;
		private int[] _damage = { 0, 0 };
		private IDFlags _identify = IDFlags.None;

		#endregion Declarations

		#region Constructor

		public InventoryItem()
		{
			this.Damage = new int[2];
		}
		public InventoryItem(int ItemNdx)
		{
			Treasure from = Treasure.Table[ItemNdx];
			this.init(from);
		}
		public InventoryItem(Treasure from)
		{
			this.init(from);
		}

		public static implicit operator Treasure(InventoryItem itm)
		{
			return itm.Treasure;
		}
		public static implicit operator InventoryItem(Treasure from)
		{
			return new InventoryItem(from);
		}
		public static implicit operator InventoryItem(int ItemNdx)
		{
			return new InventoryItem(ItemNdx);
		}

		#endregion Constructor

		#region Methods

		private void init(Treasure from)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- init ------------- ");
			this.IsDebug = from.IsDebug;
			this.Index = Treasure.Table.IndexOf(from);
			this.SpecialNameIndex = SpecialName.NULL;
			this.inscrip = string.Empty;
			this.Flags = from.Flags;
			this.Type = from.ItemType;
			this._glyph= new Glyph()
			{
						Image = null,
						Symbol = (char)from.Symbol,
						SymbolColor = Colors.Black,
			};
			this.Misc = from.Misc;
			this.Cost = from.Cost;
			this.SubCategory = from.SubType;
			this.ItemCount = from.ItemCount;
			this.Weight = from.Weight;
			this.ToHit = from.ToHit;
			this.ToDamage = from.ToDamage;
			this.ArmorClass = from.AC;
			this.ToArmorClass = from.ToAC;
			this.Damage = new int[2];
			from.Damage.CopyTo(this.Damage, 0);
			this.Level = from.Level;
			this.Identify = 0;
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

        public override string GetDescription()
        {
            return this.Treasure.Name;
        }
		public override Glyph GetGlyph()
		{
			if (this._glyph == null)
			{
				this._glyph = new Glyph()
				{
					Image = null,
					Symbol = (char)this.Treasure.Symbol,
					SymbolColor = Colors.Black,
				};
			}
			return this._glyph;
		}
		public InventoryItem Add(ItemFlag flag)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- Add(ItemFlag flag) ------------- ");
			this.Flags = this.Flags.Add<ItemFlag>(flag);
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
			return this;
		}
		public InventoryItem Remove(ItemFlag flag)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- Remove(ItemFlag flag) ------------- ");
			this.Flags = this.Flags.Remove(flag);
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
			return this;
		}
		public InventoryItem Add(IDFlags flag)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- Add(IDFlags flag) ------------- ");
			this.Identify = this.Identify.Add<IDFlags>(flag);
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
			return this;
		}
		public InventoryItem Remove(IDFlags flag)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- Remove(IDFlags flag) ------------- ");
			this.Identify = this.Identify.Remove(flag);
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
			return this;
		}

		/// <summary>
		/// was store_bought
		/// </summary>
		public void MakeStoreBought()
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MakeStoreBought ------------- ");
			this.Add(IDFlags.STOREBOUGHT);
			this.known2();
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		/* Remove "Secret" symbol for identity of plusses			*/
		private void known2()
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- known2 ------------- ");
			this.unsample();
			this.Add(IDFlags.KNOWN2);
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		/*	Remove an automatically generated inscription.	-CJS- */
		private void unsample()
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- unsample ------------- ");
			/* used to clear ID_DAMD flag, but I think it should remain set */
			this.Remove(IDFlags.MAGIK | IDFlags.EMPTY);
			int offset = this.object_offset();
			if (offset < 0) return;
			offset <<= 6;
			int indexx = this.SubCategory & (ITEM_SINGLE_STACK_MIN - 1);
			object_ident[offset + indexx].Remove(ObjectDescription.Tried);
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		private int object_offset()
		{
			switch (this.Type)
			{
				case  ItemType.AMULET: return (0);
				case ItemType.RING: return (1);
				case ItemType.STAFF: return (2);
				case ItemType.WAND: return (3);
				case ItemType.SCROLL1:
				case ItemType.SCROLL2: return (4);
				case ItemType.POTION1:
				case ItemType.POTION2: return (5);
				case ItemType.FOOD:
					if ((this.SubCategory & (ITEM_SINGLE_STACK_MIN - 1)) < Treasure.MAX_MUSH)
						return (6);
					return (-1);
				default: return (-1);
			}
		}
		/* Enchant a bonus based on degree desired -RAK- */
		private int m_bonus(int Base, int max_std, int level)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- m_bonus ------------- ");
			int stand_dev = (OBJ_STD_ADJ * level / 100) + OBJ_STD_MIN;

			/* Check for level > max_std since that may have generated an overflow.  */
			if (stand_dev > max_std || level > max_std) stand_dev = max_std;

			/* abs may be a macro, don't call it with randnor as a parameter */
			int tmp = Dice.RandNor(0, stand_dev);
			int x = (Math.Abs(tmp) / 10) + Base;

			if (x < Base) return (Base);
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
			return (x);
		}

		public void magic_treasure(int level)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- magic_treasure ------------- ");
			int chance = OBJ_BASE_MAGIC + level;
			if (chance > OBJ_BASE_MAX) chance = OBJ_BASE_MAX;

			int special = chance / OBJ_DIV_SPECIAL;
			int cursed = (10 * chance) / OBJ_DIV_CURSED;


			// some objects appear multiple times in the object_list with different
			//levels, this is to make the object occur more often, however, for
			//consistency, must set the level of these duplicates to be the same
			//as the object with the lowest level 

			// Depending on treasure type, it can have certain magical properties
			switch (this.Type)
			{

				case ItemType.SHIELD:
				case ItemType.HARD_ARMOR:
				case ItemType.SOFT_ARMOR:
					MagikArmor(level, chance, special, cursed);
					break;

				case ItemType.HAFTED:
				case ItemType.POLEARM:
				case ItemType.SWORD:
					MagikMeleeWeapon(level, chance, special, cursed);
					break;

				case ItemType.BOW:
					MagikRangedWeapon(level, chance, cursed);
					break;

				case ItemType.DIGGING:
					MagikDiggingTool(level, chance);
					break;

				case ItemType.GLOVES:
					MagikGloves(level, chance, special, cursed);
					break;

				case ItemType.BOOTS:
					MagikBoots(level, chance, special, cursed);
					break;

				case ItemType.HELM:  // Helms 
					MagikHelm(level, ref chance, ref special, cursed);
					break;

				case ItemType.RING: // Rings	      
					MagikRing(level, cursed);
					break;

				case ItemType.AMULET: // Amulets	      
					MagikAmulet(level, cursed);
					break;

				// Subval should be even for store, odd for dungeon
				// Dungeon found ones will be partially charged	 
				case ItemType.LIGHT:
					MagikLight();
					break;

				case ItemType.WAND:
					MagikWand();
					break;

				case ItemType.STAFF:
					MagikStaff();
					break;

				case ItemType.CLOAK:
					MagikCloak(level, chance, special, cursed);
					break;

				case ItemType.CHEST:
					MagikChest(level);
					break;

				case ItemType.SLING_AMMO:
				case ItemType.SPIKE:
				case ItemType.BOLT:
				case ItemType.ARROW:
					MagikAmmo(level, chance, special, cursed);
					break;

				case ItemType.FOOD:
					MagikFood();
					break;

				case ItemType.SCROLL1:
					MagikScroll();
					break;

				case ItemType.POTION1:  // potions 
					MagikPotion();
					break;

				default:
					break;
			}
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		#region magic_treasure sub-routines
		private void MagikPotion()
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MagikPotion ------------- ");
			if (this.SubCategory == 76)
				this.Level = 0;
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		private void MagikScroll()
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MagikScroll ------------- ");
			// give all identify scrolls the same level 
			if (this.SubCategory == 67) this.Level = 1;
			// scroll of light 
			else if (this.SubCategory == 69) this.Level = 0;
			// scroll of trap detection 
			else if (this.SubCategory == 80) this.Level = 5;
			// scroll of door/stair location 
			else if (this.SubCategory == 81) this.Level = 5;
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		private void MagikFood()
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MagikFood ------------- ");
			// make sure all food rations have the same level 
			if (this.SubCategory == 90)
				this.Level = 0;
			// give all elvish waybread the same level 
			else if (this.SubCategory == 92)
				this.Level = 6;
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		private void MagikAmmo(int level, int chance, int special, int cursed)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MagikAmmo ------------- ");
			if (this.Type != ItemType.SPIKE)
			{
				// always show tohit/todam values if identified 
				this.Identify |= IDFlags.SHOW_HITDAM;

				if (chance.magik())
				{
					this.ToHit += m_bonus(1, 35, level);
					this.ToDamage += m_bonus(1, 35, level);
					// see comment for weapons 
					if ((3 * special / 2).magik())
					{
						switch (Dice.RandInt(10))
						{
							case 1:
							case 2:
							case 3:
								this.SpecialNameIndex = SpecialName.SLAYING;
								this.ToHit += 5;
								this.ToDamage += 5;
								this.Cost += 20;
								break;
							case 4:
							case 5:

								this.Add(ItemFlag.FLAME_TONGUE);

								this.ToHit += 2;
								this.ToDamage += 4;
								this.SpecialNameIndex = SpecialName.FIRE;
								this.Cost += 25;
								break;
							case 6:
							case 7:
								this.Add(ItemFlag.SLAY_EVIL);
								this.ToHit += 3;
								this.ToDamage += 3;
								this.SpecialNameIndex = SpecialName.SLAY_EVIL;
								this.Cost += 25;
								break;
							case 8:
							case 9:
								this.Add(ItemFlag.SLAY_ANIMAL);
								this.ToHit += 2;
								this.ToDamage += 2;
								this.SpecialNameIndex = SpecialName.SLAY_ANIMAL;
								this.Cost += 30;
								break;
							case 10:
								this.Add(ItemFlag.SLAY_DRAGON);
								this.ToHit += 3;
								this.ToDamage += 3;
								this.SpecialNameIndex = SpecialName.DRAGON_SLAYING;
								this.Cost += 35;
								break;
						}
					}
				}
				else if (cursed.magik())
				{
					this.ToHit -= m_bonus(5, 55, level);
					this.ToDamage -= m_bonus(5, 55, level);

					this.Add(ItemFlag.CURSED);

					this.Cost = 0;
				}
			}

			this.ItemCount = 0;

			for (int i = 0; i < 7; i++)
				this.ItemCount += Dice.RandInt(6);

			//if (missile_ctr == MAX_SHORT)
			//   missile_ctr = -MAX_SHORT - 1;
			//else
			//   missile_ctr++;
			//this.Misc = missile_ctr;
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		private void MagikChest(int level)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MagikChest ------------- ");
			switch (Dice.RandInt(level + 4))
			{
				case 1:
					this.Flags = 0;
					this.SpecialNameIndex = SpecialName.EMPTY;
					break;
				case 2:
					this.Add(ItemFlag.LOCKED_CHEST);
					this.SpecialNameIndex = SpecialName.LOCKED;
					break;
				case 3:
				case 4:
					this.Add(ItemFlag.LOSE_STR_CHESTTRAP | ItemFlag.LOCKED_CHEST);
					this.SpecialNameIndex = SpecialName.POISON_NEEDLE;
					break;
				case 5:
				case 6:
					this.Add(ItemFlag.POISON_CHESTTRAP | ItemFlag.LOCKED_CHEST);
					this.SpecialNameIndex = SpecialName.POISON_NEEDLE;
					break;
				case 7:
				case 8:
				case 9:
					this.Add(ItemFlag.PARALYSED_CHESTTRAP | ItemFlag.LOCKED_CHEST);
					this.SpecialNameIndex = SpecialName.GAS_TRAP;
					break;
				case 10:
				case 11:
					this.Add(ItemFlag.EXPLODE_CHESTTRAP | ItemFlag.LOCKED_CHEST);
					this.SpecialNameIndex = SpecialName.EXPLOSION_DEVICE;
					break;
				case 12:
				case 13:
				case 14:
					this.Add(ItemFlag.SUMMON_CHESTTRAP | ItemFlag.LOCKED_CHEST);
					this.SpecialNameIndex = SpecialName.SUMMONING_RUNES;
					break;
				case 15:
				case 16:
				case 17:
					this.Add(ItemFlag.PARALYSED_CHESTTRAP | ItemFlag.POISON_CHESTTRAP | ItemFlag.LOSE_STR_CHESTTRAP | ItemFlag.LOCKED_CHEST);
					this.SpecialNameIndex = SpecialName.MULTIPLE_TRAPS;
					break;
				default:
					this.Add(ItemFlag.SUMMON_CHESTTRAP | ItemFlag.EXPLODE_CHESTTRAP | ItemFlag.LOCKED_CHEST);
					this.SpecialNameIndex = SpecialName.MULTIPLE_TRAPS;
					break;
			}
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		private void MagikCloak(int level, int chance, int special, int cursed)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MagikCloak ------------- ");
			if (chance.magik())
			{
				if (special.magik())
				{
					if (Dice.RandInt(2) == 1)
					{
						this.SpecialNameIndex = SpecialName.PROTECTION;
						this.ToArmorClass += m_bonus(2, 40, level);
						this.Cost += 250;
					}
					else
					{
						this.ToArmorClass += m_bonus(1, 20, level);
						this.Identify |= IDFlags.SHOW_P1;
						this.Misc = Dice.RandInt(3);
						this.Add(ItemFlag.STEALTH);
						this.SpecialNameIndex = SpecialName.STEALTH;
						this.Cost += 500;
					}
				}
				else
				{
					this.ToArmorClass += m_bonus(1, 20, level);
				}
			}
			else if (cursed.magik())
			{
				int tmp = Dice.RandInt(3);
				if (tmp == 1)
				{
					this.Add(ItemFlag.AGGRAVATE);
					this.SpecialNameIndex = SpecialName.IRRITATION;
					this.ToArmorClass -= m_bonus(1, 10, level);
					this.Identify |= IDFlags.SHOW_HITDAM;
					this.ToHit -= m_bonus(1, 10, level);
					this.ToDamage -= m_bonus(1, 10, level);
					this.Cost = 0;
				}
				else if (tmp == 2)
				{
					this.SpecialNameIndex = SpecialName.VULNERABILITY;
					this.ToArmorClass -= m_bonus(10, 100, level + 50);
					this.Cost = 0;
				}
				else
				{
					this.SpecialNameIndex = SpecialName.ENVELOPING;
					this.ToArmorClass -= m_bonus(1, 10, level);
					this.Identify |= IDFlags.SHOW_HITDAM;
					this.ToHit -= m_bonus(2, 40, level + 10);
					this.ToDamage -= m_bonus(2, 40, level + 10);
					this.Cost = 0;
				}

				this.Add(ItemFlag.CURSED);

			}
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		private void MagikStaff()
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MagikStaff ------------- ");
			switch (this.SubCategory)
			{
				case 0: this.Misc = Dice.RandInt(20) + 12; break;
				case 1: this.Misc = Dice.RandInt(8) + 6; break;
				case 2: this.Misc = Dice.RandInt(5) + 6; break;
				case 3: this.Misc = Dice.RandInt(20) + 12; break;
				case 4: this.Misc = Dice.RandInt(15) + 6; break;
				case 5: this.Misc = Dice.RandInt(4) + 5; break;
				case 6: this.Misc = Dice.RandInt(5) + 3; break;
				case 7: this.Misc = Dice.RandInt(3) + 1;
					this.Level = 10;
					break;
				case 8: this.Misc = Dice.RandInt(3) + 1; break;
				case 9: this.Misc = Dice.RandInt(5) + 6; break;
				case 10: this.Misc = Dice.RandInt(10) + 12; break;
				case 11: this.Misc = Dice.RandInt(5) + 6; break;
				case 12: this.Misc = Dice.RandInt(5) + 6; break;
				case 13: this.Misc = Dice.RandInt(5) + 6; break;
				case 14: this.Misc = Dice.RandInt(10) + 12; break;
				case 15: this.Misc = Dice.RandInt(3) + 4; break;
				case 16: this.Misc = Dice.RandInt(5) + 6; break;
				case 17: this.Misc = Dice.RandInt(5) + 6; break;
				case 18: this.Misc = Dice.RandInt(3) + 4; break;
				case 19: this.Misc = Dice.RandInt(10) + 12; break;
				case 20: this.Misc = Dice.RandInt(3) + 4; break;
				case 21: this.Misc = Dice.RandInt(3) + 4; break;
				case 22: this.Misc = Dice.RandInt(10) + 6;
					this.Level = 5;
					break;
				default:
					break;
			}
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		private void MagikWand()
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MagikWand ------------- ");
			switch (this.SubCategory)
			{
				case 0: this.Misc = Dice.RandInt(10) + 6; break;
				case 1: this.Misc = Dice.RandInt(8) + 6; break;
				case 2: this.Misc = Dice.RandInt(5) + 6; break;
				case 3: this.Misc = Dice.RandInt(8) + 6; break;
				case 4: this.Misc = Dice.RandInt(4) + 3; break;
				case 5: this.Misc = Dice.RandInt(8) + 6; break;
				case 6: this.Misc = Dice.RandInt(20) + 12; break;
				case 7: this.Misc = Dice.RandInt(20) + 12; break;
				case 8: this.Misc = Dice.RandInt(10) + 6; break;
				case 9: this.Misc = Dice.RandInt(12) + 6; break;
				case 10: this.Misc = Dice.RandInt(10) + 12; break;
				case 11: this.Misc = Dice.RandInt(3) + 3; break;
				case 12: this.Misc = Dice.RandInt(8) + 6; break;
				case 13: this.Misc = Dice.RandInt(10) + 6; break;
				case 14: this.Misc = Dice.RandInt(5) + 3; break;
				case 15: this.Misc = Dice.RandInt(5) + 3; break;
				case 16: this.Misc = Dice.RandInt(5) + 6; break;
				case 17: this.Misc = Dice.RandInt(5) + 4; break;
				case 18: this.Misc = Dice.RandInt(8) + 4; break;
				case 19: this.Misc = Dice.RandInt(6) + 2; break;
				case 20: this.Misc = Dice.RandInt(4) + 2; break;
				case 21: this.Misc = Dice.RandInt(8) + 6; break;
				case 22: this.Misc = Dice.RandInt(5) + 2; break;
				case 23: this.Misc = Dice.RandInt(12) + 12; break;
				default:
					break;
			}
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		private void MagikLight()
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MagikLight ------------- ");
			if ((this.SubCategory % 2) == 1)
			{
				this.Misc = Dice.RandInt(this.Misc);
				this.SubCategory -= 1;
			}
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		private void MagikAmulet(int level, int cursed)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MagikAmulet ------------- ");
			if (this.SubCategory < 2)
			{
				if (cursed.magik())
				{
					this.Misc = -m_bonus(1, 20, level);
					this.Add(ItemFlag.CURSED);
					this.Cost = -this.Cost;
				}
				else
				{
					this.Misc = m_bonus(1, 10, level);
					this.Cost += this.Misc * 100;
				}
			}
			else if (this.SubCategory == 2)
			{
				this.Misc = 5 * m_bonus(1, 25, level);
				if (cursed.magik())
				{
					this.Misc = -this.Misc;
					this.Cost = -this.Cost;

					this.Add(ItemFlag.CURSED);

				}
				else
				{
					this.Cost += 50 * this.Misc;
				}
			}
			else if (this.SubCategory == 8)
			{
				// amulet of the magi is never cursed 
				this.Misc = 5 * m_bonus(1, 25, level);
				this.Cost += 20 * this.Misc;
			}
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		private void MagikRing(int level, int cursed)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MagikRing ------------- ");
			switch (this.SubCategory)
			{
				case 0:
				case 1:
				case 2:
				case 3:
					if (cursed.magik())
					{
						this.Misc = -m_bonus(1, 20, level);
						this.Add(ItemFlag.CURSED);
						this.Cost = -this.Cost;
					}
					else
					{
						this.Misc = m_bonus(1, 10, level);
						this.Cost += this.Misc * 100;
					}
					break;
				case 4:
					if (cursed.magik())
					{
						this.Misc = -Dice.RandInt(3);
						this.Add(ItemFlag.CURSED);
						this.Cost = -this.Cost;
					}
					else
					{
						this.Misc = 1;
					}
					break;
				case 5:
					this.Misc = 5 * m_bonus(1, 20, level);
					this.Cost += this.Misc * 50;
					if (cursed.magik())
					{
						this.Misc = -this.Misc;
						this.Add(ItemFlag.CURSED);
						this.Cost = -this.Cost;
					}
					break;
				case 19:     // Increase damage	      
					this.ToDamage += m_bonus(1, 20, level);
					this.Cost += this.ToDamage * 100;
					if (cursed.magik())
					{
						this.ToDamage = -this.ToDamage;
						this.Add(ItemFlag.CURSED);
						this.Cost = -this.Cost;
					}
					break;
				case 20:     // Increase To-Hit	      
					this.ToHit += m_bonus(1, 20, level);
					this.Cost += this.ToHit * 100;
					if (cursed.magik())
					{
						this.ToHit = -this.ToHit;
						this.Add(ItemFlag.CURSED);
						this.Cost = -this.Cost;
					}
					break;
				case 21:     // Protection	      
					this.ToArmorClass += m_bonus(1, 20, level);
					this.Cost += this.ToArmorClass * 100;
					if (cursed.magik())
					{
						this.ToArmorClass = -this.ToArmorClass;
						this.Add(ItemFlag.CURSED);
						this.Cost = -this.Cost;
					}
					break;
				case 24:
				case 25:
				case 26:
				case 27:
				case 28:
				case 29:
					this.Identify |= IDFlags.NOSHOW_P1;
					break;
				case 30:     // Slaying	      
					this.Identify |= IDFlags.SHOW_HITDAM;
					this.ToDamage += m_bonus(1, 25, level);
					this.ToHit += m_bonus(1, 25, level);
					this.Cost += (this.ToHit + this.ToDamage) * 100;
					if (cursed.magik())
					{
						this.ToHit = -this.ToHit;
						this.ToDamage = -this.ToDamage;

						this.Add(ItemFlag.CURSED);

						this.Cost = -this.Cost;
					}
					break;
				default:
					break;
			}
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		private void MagikHelm(int level, ref int chance, ref int special, int cursed)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MagikHelm ------------- ");
			if ((this.SubCategory >= 6) && (this.SubCategory <= 8))
			{
				// give crowns a higher chance for magic 
				chance += (int)(this.Cost / 100);
				special += special;
			}

			if (chance.magik())
			{
				this.ToArmorClass += m_bonus(1, 20, level);
				if (special.magik())
				{
					if (this.SubCategory < 6)
					{
						int tmp = Dice.RandInt(3);
						this.Identify |= IDFlags.SHOW_P1;
						if (tmp == 1)
						{
							this.Misc = Dice.RandInt(2);
							this.Add(ItemFlag.INT);
							this.SpecialNameIndex = SpecialName.INTELLIGENCE;
							this.Cost += this.Misc * 500;
						}
						else if (tmp == 2)
						{
							this.Misc = Dice.RandInt(2);
							this.Add(ItemFlag.WIS);
							this.SpecialNameIndex = SpecialName.WISDOM;
							this.Cost += this.Misc * 500;
						}
						else
						{
							this.Misc = 1 + Dice.RandInt(4);
							this.Add(ItemFlag.INFRA);
							this.SpecialNameIndex = SpecialName.INFRAVISION;
							this.Cost += this.Misc * 250;
						}
					}
					else
					{
						switch (Dice.RandInt(6))
						{
							case 1:
								this.Identify |= IDFlags.SHOW_P1;
								this.Misc = Dice.RandInt(3);
								this.Add(ItemFlag.FREE_ACT | ItemFlag.CON | ItemFlag.DEX | ItemFlag.STR);
								this.SpecialNameIndex = SpecialName.MIGHT;
								this.Cost += 1000 + this.Misc * 500;
								break;
							case 2:
								this.Identify |= IDFlags.SHOW_P1;
								this.Misc = Dice.RandInt(3);
								this.Add(ItemFlag.CHR | ItemFlag.WIS);
								this.SpecialNameIndex = SpecialName.LORDLINESS;
								this.Cost += 1000 + this.Misc * 500;
								break;
							case 3:
								this.Identify |= IDFlags.SHOW_P1;
								this.Misc = Dice.RandInt(3);
								this.Add(ItemFlag.RES_LIGHT | ItemFlag.RES_COLD | ItemFlag.ResistAcid | ItemFlag.RES_FIRE | ItemFlag.INT);
								this.SpecialNameIndex = SpecialName.MAGI;
								this.Cost += 3000 + this.Misc * 500;
								break;
							case 4:
								this.Identify |= IDFlags.SHOW_P1;
								this.Misc = Dice.RandInt(3);
								this.Add(ItemFlag.CHR);
								this.SpecialNameIndex = SpecialName.BEAUTY;
								this.Cost += 750;
								break;
							case 5:
								this.Identify |= IDFlags.SHOW_P1;
								this.Misc = 5 * (1 + Dice.RandInt(4));
								this.Add(ItemFlag.SEE_INVIS | ItemFlag.SEARCH);
								this.SpecialNameIndex = SpecialName.SEEING;
								this.Cost += 1000 + this.Misc * 100;
								break;
							case 6:
								this.Add(ItemFlag.REGEN);
								this.SpecialNameIndex = SpecialName.REGENERATION;
								this.Cost += 1500;
								break;
						}
					}
				}
			}
			else if (cursed.magik())
			{
				this.ToArmorClass -= m_bonus(1, 45, level);

				this.Add(ItemFlag.CURSED);

				this.Cost = 0;
				if (special.magik())
					switch (Dice.RandInt(7))
					{
						case 1:
							this.Identify |= IDFlags.SHOW_P1;
							this.Misc = -Dice.RandInt(5);
							this.Add(ItemFlag.INT);
							this.SpecialNameIndex = SpecialName.STUPIDITY;
							break;
						case 2:
							this.Identify |= IDFlags.SHOW_P1;
							this.Misc = -Dice.RandInt(5);
							this.Add(ItemFlag.WIS);
							this.SpecialNameIndex = SpecialName.DULLNESS;
							break;
						case 3:

							this.Add(ItemFlag.BLIND);

							this.SpecialNameIndex = SpecialName.BLINDNESS;
							break;
						case 4:

							this.Add(ItemFlag.TIMID);

							this.SpecialNameIndex = SpecialName.TIMIDNESS;
							break;
						case 5:
							this.Identify |= IDFlags.SHOW_P1;
							this.Misc = -Dice.RandInt(5);
							this.Add(ItemFlag.STR);
							this.SpecialNameIndex = SpecialName.WEAKNESS;
							break;
						case 6:
							this.Add(ItemFlag.TELEPORT);
							this.SpecialNameIndex = SpecialName.TELEPORTATION;
							break;
						case 7:
							this.Identify |= IDFlags.SHOW_P1;
							this.Misc = -Dice.RandInt(5);
							this.Add(ItemFlag.CHR);
							this.SpecialNameIndex = SpecialName.UGLINESS;
							break;
					}
			}
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		private void MagikBoots(int level, int chance, int special, int cursed)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MagikBoots ------------- ");
			if (chance.magik())
			{
				this.ToArmorClass += m_bonus(1, 20, level);
				if (special.magik())
				{
					int tmp = Dice.RandInt(12);
					if (tmp > 5)
					{
						this.Add(ItemFlag.FFALL);
						this.SpecialNameIndex = SpecialName.SLOW_DESCENT;
						this.Cost += 250;
					}
					else if (tmp == 1)
					{
						this.Add(ItemFlag.SPEED);
						this.SpecialNameIndex = SpecialName.SPEED;
						this.Identify |= IDFlags.SHOW_P1;
						this.Misc = 1;
						this.Cost += 5000;
					}
					else // 2 - 5 
					{
						this.Add(ItemFlag.STEALTH);
						this.Identify |= IDFlags.SHOW_P1;
						this.Misc = Dice.RandInt(3);
						this.SpecialNameIndex = SpecialName.STEALTH;
						this.Cost += 500;
					}
				}
			}
			else if (cursed.magik())
			{
				int tmp = Dice.RandInt(3);
				if (tmp == 1)
				{
					this.Add(ItemFlag.SPEED);
					this.SpecialNameIndex = SpecialName.SLOWNESS;
					this.Identify |= IDFlags.SHOW_P1;
					this.Misc = -1;
				}
				else if (tmp == 2)
				{
					this.Add(ItemFlag.AGGRAVATE);
					this.SpecialNameIndex = SpecialName.NOISE;
				}
				else
				{
					this.SpecialNameIndex = SpecialName.GREAT_MASS;
					this.Weight *= 5;
				}
				this.Cost = 0;
				this.ToArmorClass -= m_bonus(2, 45, level);
				this.Add(ItemFlag.CURSED);
			}
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		private void MagikGloves(int level, int chance, int special, int cursed)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MagikGloves ------------- ");
			if (chance.magik())
			{
				this.ToArmorClass += m_bonus(1, 20, level);
				if (special.magik())
				{
					if (Dice.RandInt(2) == 1)
					{
						this.Add(ItemFlag.FREE_ACT);
						this.SpecialNameIndex = SpecialName.FREE_ACTION;
						this.Cost += 1000;
					}
					else
					{
						this.Identify |= IDFlags.SHOW_HITDAM;
						this.ToHit += 1 + Dice.RandInt(3);
						this.ToDamage += 1 + Dice.RandInt(3);
						this.SpecialNameIndex = SpecialName.SLAYING;
						this.Cost += (this.ToHit + this.ToDamage) * 250;
					}
				}
			}
			else if (cursed.magik())
			{
				if (special.magik())
				{
					if (Dice.RandInt(2) == 1)
					{
						this.Add(ItemFlag.DEX);
						this.SpecialNameIndex = SpecialName.CLUMSINESS;
					}
					else
					{
						this.Add(ItemFlag.STR);
						this.SpecialNameIndex = SpecialName.WEAKNESS;
					}
					this.Identify |= IDFlags.SHOW_P1;
					this.Misc = -m_bonus(1, 10, level);
				}
				this.ToArmorClass -= m_bonus(1, 40, level);
				this.Add(ItemFlag.CURSED);
				this.Cost = 0;
			}
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		private void MagikDiggingTool(int level, int chance)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MagikDiggingTool ------------- ");
			// always show tohit/todam values if identified 
			this.Identify |= IDFlags.SHOW_HITDAM;
			if (chance.magik())
			{
				int tmp = Dice.RandInt(3);
				if (tmp < 3)
				{
					this.Misc += m_bonus(0, 25, level);
				}
				else
				{
					// a cursed digging tool 
					this.Misc = -m_bonus(1, 30, level);
					this.Cost = 0;
					this.Add(ItemFlag.CURSED);
				}
			}
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		private void MagikRangedWeapon(int level, int chance, int cursed)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MagikRangedWeapon ------------- ");
			// always show tohit/todam values if identified 
			this.Identify.Add(IDFlags.SHOW_HITDAM);
			if (chance.magik())
			{
				this.ToHit += m_bonus(1, 30, level);
				this.ToDamage += m_bonus(1, 20, level); // add damage. -CJS- 
			}
			else if (cursed.magik())
			{
				this.ToHit -= m_bonus(1, 50, level);
				this.ToDamage -= m_bonus(1, 30, level); // add damage. -CJS- 
				this.Add(ItemFlag.CURSED);
				this.Cost = 0;
			}
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		private void MagikMeleeWeapon(int level, int chance, int special, int cursed)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MagikMeleeWeapon ------------- ");
			// always show tohit/todam values if identified 
			this.Identify.Add(IDFlags.SHOW_HITDAM);
			if (chance.magik())
			{
				this.ToHit += m_bonus(0, 40, level);
				// Magical damage bonus now proportional to weapon base damage 
				int tmp = this.Damage[0] * this.Damage[1];
				this.ToDamage += m_bonus(0, 4 * tmp, tmp * level / 10);
				// the 3*special/2 is needed because weapons are not as common as
				//before change to treasure distribution, this helps keep same
				//number of ego weapons same as before, see also missiles 
				if ((3 * special / 2).magik())
					switch (Dice.RandInt(16))
					{
						case 1:	// Holy Avenger	 
							this.Add(ItemFlag.SEE_INVIS | ItemFlag.SUST_STAT | ItemFlag.SLAY_UNDEAD | ItemFlag.SLAY_EVIL | ItemFlag.STR);
							this.ToHit += 5;
							this.ToDamage += 5;
							this.ToArmorClass += Dice.RandInt(4);
							// the value in Misc is used for strength increase 
							// Misc is also used for sustain stat 
							this.Misc = Dice.RandInt(4);
							this.SpecialNameIndex = SpecialName.HA;
							this.Cost += this.Misc * 500;
							this.Cost += 10000;
							break;
						case 2:	// Defender	 
							this.Add(ItemFlag.FFALL | ItemFlag.RES_LIGHT | ItemFlag.SEE_INVIS | ItemFlag.FREE_ACT | ItemFlag.RES_COLD | ItemFlag.ResistAcid | ItemFlag.RES_FIRE | ItemFlag.REGEN | ItemFlag.STEALTH);
							this.ToHit += 3;
							this.ToDamage += 3;
							this.ToArmorClass += 5 + Dice.RandInt(5);
							this.SpecialNameIndex = SpecialName.DF;
							// the value in Misc is used for stealth 
							this.Misc = Dice.RandInt(3);
							this.Cost += this.Misc * 500;
							this.Cost += 7500;
							break;
						case 3:
						case 4:	 // Slay Animal  
							this.Add(ItemFlag.SLAY_ANIMAL);
							this.ToHit += 3;
							this.ToDamage += 3;
							this.SpecialNameIndex = SpecialName.SA;
							this.Cost += 5000;
							break;
						case 5:
						case 6:	// Slay Dragon	 
							this.Add(ItemFlag.SLAY_DRAGON);
							this.ToHit += 3;
							this.ToDamage += 3;
							this.SpecialNameIndex = SpecialName.SD;
							this.Cost += 4000;
							break;
						case 7:
						case 8:	  // Slay Evil	   
							this.Add(ItemFlag.SLAY_EVIL);
							this.ToHit += 3;
							this.ToDamage += 3;
							this.SpecialNameIndex = SpecialName.SE;
							this.Cost += 4000;
							break;
						case 9:
						case 10:	 // Slay Undead	  
							this.Add(ItemFlag.SEE_INVIS | ItemFlag.SLAY_UNDEAD);
							this.ToHit += 2;
							this.ToDamage += 2;
							this.SpecialNameIndex = SpecialName.SU;
							this.Cost += 3000;
							break;
						case 11:
						case 12:
						case 13:   // Flame Tongue  
							this.Add(ItemFlag.FLAME_TONGUE);
							this.ToHit++;
							this.ToDamage += 3;
							this.SpecialNameIndex = SpecialName.FT;
							this.Cost += 2000;
							break;
						case 14:
						case 15:
						case 16:   // Frost Brand   
							this.Add(ItemFlag.FROST_BRAND);
							this.ToHit++;
							this.ToDamage++;
							this.SpecialNameIndex = SpecialName.FB;
							this.Cost += 1200;
							break;
					}
			}
			else if (cursed.magik())
			{
				this.ToHit -= m_bonus(1, 55, level);
				// Magical damage bonus now proportional to weapon base damage 
				int tmp = this.Damage[0] * this.Damage[1];
				this.ToDamage -= m_bonus(1, 11 * tmp / 2, tmp * level / 10);
				this.Add(ItemFlag.CURSED);
				this.Cost = 0;
			}
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}

		private void MagikArmor(int level, int chance, int special, int cursed)
		{
			Drawable.WriteLineIf(this.IsDebug, "-------------- MagikArmor ------------- ");
			if (chance.magik())
			{
				this.ToArmorClass += m_bonus(1, 30, level);
				if (special.magik())
					switch (Dice.RandInt(9))
					{
						case 1:
							this.Add(ItemFlag.RES_LIGHT | ItemFlag.RES_COLD | ItemFlag.ResistAcid | ItemFlag.RES_FIRE);
							this.SpecialNameIndex = SpecialName.R;
							this.ToArmorClass += 5;
							this.Cost += 2500;
							break;
						case 2:	 // Resist Acid	  
							this.Add(ItemFlag.ResistAcid);
							this.SpecialNameIndex = SpecialName.RA;
							this.Cost += 1000;
							break;
						case 3:
						case 4:	 // Resist Fire	  
							this.Add(ItemFlag.RES_FIRE);
							this.SpecialNameIndex = SpecialName.RF;
							this.Cost += 600;
							break;
						case 5:
						case 6:	// Resist Cold	 
							this.Add(ItemFlag.RES_COLD);
							this.SpecialNameIndex = SpecialName.RC;
							this.Cost += 600;
							break;
						case 7:
						case 8:
						case 9:  // Resist Lightning
							this.Add(ItemFlag.RES_LIGHT);
							this.SpecialNameIndex = SpecialName.RL;
							this.Cost += 500;
							break;
					}
			}
			else if (cursed.magik())
			{
				this.ToArmorClass -= m_bonus(1, 40, level);
				this.Cost = 0;
				this.Add(ItemFlag.CURSED);
			}
			Drawable.WriteLineIf(this.IsDebug, "----------------------------------------- ");
		}
		#endregion magic_treasure sub-routines

		#endregion Methods

		#region Events


		#endregion Events

		#region Properties

		public Treasure Treasure { get { return Treasure.Table[this.Index]; } }

		public string Name { get { return this.Treasure.Name; } }
		public int Index { get; set; }		// Index to Treasure.Table 
		public SpecialName SpecialNameIndex { get; set; }		// Object special Name  
		/// was tval
		public ItemType Type { get; private set; }		// Item ItemType 
		//public int Symbol { get; set; }		// Character representation
		public int SubCategory { get; set; }		// Sub-category ItemCount	
		public int Level { get; set; }		// Level item first found 

		public InventoryLocation Location
		{
			get { return this._location; }
			set
			{
				if (value == this._location) return;
				this._location = value;
				this.RaisePropertyChanged(() => this.Location);
			}
		}
		public string inscrip
		{
			get { return this._inscrip; }
			set
			{
				if (value == this._inscrip) return;
				this._inscrip = value;
				this.RaisePropertyChanged(() => this.inscrip);
			}
		}		// Object inscription   
		public ItemFlag Flags
		{
			get { return this._flags; }
			set
			{
				if (value == this._flags) return;
				this._flags = value;
				this.RaisePropertyChanged(() => this.Flags);
			}
		}		// Special flags	
		public int Misc
		{
			get { return this._misc; }
			set
			{
				if (value == this._misc) return;
				this._misc = value;
				this.RaisePropertyChanged(() => this.Misc);
			}
		}				// Misc. use variable	
		public int Cost
		{
			get { return this._cost; }
			set
			{
				if (value == this._cost) return;
				this._cost = value;
				this.RaisePropertyChanged(() => this.Cost);
			}
		}				// Cost of item		
		public int ItemCount
		{
			get { return this._itemCount; }
			set
			{
				if (value == this._itemCount) return;
				this._itemCount = value;
				this.RaisePropertyChanged(() => this.ItemCount);
			}
		}			// Number of Items	
		public int Weight
		{
			get { return this._weight; }
			set
			{
				if (value == this._weight) return;
				this._weight = value;
				this.RaisePropertyChanged(() => this.Weight);
			}
		}				// Weight		
		public int ToHit
		{
			get { return this._toHit; }
			set
			{
				if (value == this._toHit) return;
				this._toHit = value;
				this.RaisePropertyChanged(() => this.ToHit);
			}
		}				// Plusses to hit	
		public int ToDamage
		{
			get { return this._toDamage; }
			set
			{
				if (value == this._toDamage) return;
				this._toDamage = value;
				this.RaisePropertyChanged(() => this.ToDamage);
			}
		}			// Plusses to Damage	
		public int ArmorClass
		{
			get { return this._armorClass; }
			set
			{
				if (value == this._armorClass) return;
				this._armorClass = value;
				this.RaisePropertyChanged(() => this.ArmorClass);
			}
		}		// Normal AC		
		/// was toac
		public int ToArmorClass
		{
			get { return this._toArmorClass; }
			set
			{
				if (value == this._toArmorClass) return;
				this._toArmorClass = value;
				this.RaisePropertyChanged(() => this.ToArmorClass);
			}
		}		// Plusses to AC	
		public int[] Damage
		{
			get { return this._damage; }
			private set
			{
				if (value == this._damage) return;
				this._damage = value;
				this.RaisePropertyChanged(() => this.Damage);
			}
		}			// Damage when hits	
		public IDFlags Identify
		{
			get { return this._identify; }
			set
			{
				if (value == this._identify) return;
				this._identify = value;
				this.RaisePropertyChanged(() => this.Identify);
			}
		}		// Identify information 	

		#endregion Properties


		//TODO: calculate the value of the item
		public int Value { get { return 0; } }


	}
}
